package com.aspire.nm.component.cmppserver.handler;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

import javax.annotation.Resource;

import org.apache.mina.core.session.IoSession;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.aspire.nm.component.cmppserver.CmppServer;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppDeliverPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppSubmitPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.CmppSubmitRespPacket;
import com.aspire.nm.component.cmppserver.filter.coder.packet.Version;
import com.aspire.nm.component.cmppserver.runTime.SysRunTimeService;
import com.aspire.nm.component.cmppserver.runTime.UserRunTime;
import com.aspire.nm.component.cmppserver.util.InvokeRateUtil;
import com.aspire.nm.component.cmppserver.util.LogService;
import com.aspire.nm.component.cmppserver.util.MessageIdGenerator;
import com.aspire.nm.component.commonUtil.date.DateUtil;


@Service
public class ProcessSubmitManager{

    
    
    @Resource
    private CmppServer cmppServer;
    
	@Resource(name="submitExecutor")
	private Executor submitExecutor;
	
	@Resource
    private SysRunTimeService sysRunTimeService;
	
	@Value("${cmppserver.splitSubmitMsg}")
    private boolean splitSubmitMsg;
	
	@Value("${cmppserver.syncProcessSubmit}")
    private boolean syncProcessSubmit;
	
	@Value("${autoDeliver}")
    private boolean autoDeliver;
	
	@Resource
    private LogService logService;
	
	
	public int process(IoSession session,CmppSubmitPacket cmppSubmitPacket,CmppSubmitRespPacket cmppSubmitRespPacket){
	    if(syncProcessSubmit){
	        return processSync(session,cmppSubmitPacket,cmppSubmitRespPacket);
	    }else{
	        return processAsync(session,cmppSubmitPacket,cmppSubmitRespPacket);
	    }
	}
	
	
	public int processAsync(IoSession session,CmppSubmitPacket cmppSubmitPacket,CmppSubmitRespPacket cmppSubmitRespPacket){
		try{
    	    submitExecutor.execute(new Thread(){
    			private CmppSubmitPacket cmppSubmitPacket;
    			private CmppSubmitRespPacket cmppSubmitRespPacket;
    			private IoSession session;
    			public Runnable setParams(IoSession session,CmppSubmitPacket cmppSubmitPacket,CmppSubmitRespPacket cmppSubmitRespPacket){
    				this.cmppSubmitPacket = cmppSubmitPacket;
    				this.cmppSubmitRespPacket = cmppSubmitRespPacket;
    				this.session = session;
    				return this;
    			}
    			public void run(){
    			    processSync(session,cmppSubmitPacket,cmppSubmitRespPacket);
    			}
    		}.setParams(session,cmppSubmitPacket,cmppSubmitRespPacket));
		}
		catch(java.util.concurrent.RejectedExecutionException re){
		    re.printStackTrace();
        }
		return CmppSubmitRespPacket.RESULT_OK;
	}


	
	
	private int processSync(IoSession session,CmppSubmitPacket cmppSubmitPacket,CmppSubmitRespPacket cmppSubmitRespPacket){
	    String clientIp = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
	    String user = sysRunTimeService.getUserRunTime(session).getUser();
	    
	    if(cmppServer.getProcessSubmit() != null){
            if(splitSubmitMsg){
                
                List<SubmitReqResp> submitReqResps = getSubmitReqResps(cmppSubmitPacket,cmppSubmitRespPacket,sysRunTimeService.getUserRunTime(session).getConnection(session).getVersion());
                int result  =  -1;
                for(SubmitReqResp submitReqResp : submitReqResps){
                    logService.processSubmit(session, submitReqResp.cmppSubmitPacket);
                    int tmpresult =  cmppServer.getProcessSubmit().process(submitReqResp.cmppSubmitPacket,submitReqResp.cmppSubmitRespPacket,user,clientIp);
                    //只要一个成功则算成功
                    if(result == -1){
                        result = tmpresult;
                    }
                    if(tmpresult == CmppSubmitRespPacket.RESULT_OK){
                        result = CmppSubmitRespPacket.RESULT_OK;
                    }
                    if(autoDeliver && tmpresult == CmppSubmitRespPacket.RESULT_OK){
                        autoDeliver(submitReqResp.cmppSubmitPacket,submitReqResp.cmppSubmitRespPacket,user,clientIp);
                    }
                }
                
                return result;
            }else{
                logService.processSubmit(session, cmppSubmitPacket);
                int result = cmppServer.getProcessSubmit().process(cmppSubmitPacket,cmppSubmitRespPacket,user,clientIp);
                
                if(autoDeliver && result == CmppSubmitRespPacket.RESULT_OK){
                    List<SubmitReqResp> submitReqResps = getSubmitReqResps(cmppSubmitPacket,cmppSubmitRespPacket,sysRunTimeService.getUserRunTime(session).getConnection(session).getVersion());
                    for(SubmitReqResp submitReqResp : submitReqResps){
                        autoDeliver(submitReqResp.cmppSubmitPacket,submitReqResp.cmppSubmitRespPacket,user,clientIp);
                    }
                }
                return result;
            }
        }
	    return CmppSubmitRespPacket.RESULT_OK;
	}
	
	
	
	
	
	
	private void autoDeliver(CmppSubmitPacket cmppSubmitPacket, CmppSubmitRespPacket cmppSubmitRespPacket, final String user,String clientIp){
        
	    final CmppDeliverPacket cmppDeliverPacket = new CmppDeliverPacket();
        
        if(cmppSubmitPacket.getRegisteredDelivery() == 1){
            //自动返回状态报告
            cmppDeliverPacket.setDestId(cmppSubmitPacket.getSrcId());
            cmppDeliverPacket.setDestTerminalId(cmppSubmitPacket.getDestTerminateIds());
            cmppDeliverPacket.setRegisteredDelivery(true);
            cmppDeliverPacket.setSrcTerminalId(cmppSubmitPacket.getDestTerminateIds());
            cmppDeliverPacket.setSrcTerminalType((byte)0);
            cmppDeliverPacket.setServiceId(cmppSubmitPacket.getServiceId());
            cmppDeliverPacket.setMsgId(MessageIdGenerator.getMessageIdGenerator().getMsgId((short)0));
            cmppDeliverPacket.setIsmgMsgId(cmppSubmitRespPacket.getMsgId());
            cmppDeliverPacket.setStat("DELIVRD");
            cmppDeliverPacket.setSubmitTime(DateUtil.getCurDateTimeFormat("yyMMddHHmm"));
            cmppDeliverPacket.setDoneTime(DateUtil.getCurDateTimeFormat("yyMMddHHmm"));
            try {
                cmppDeliverPacket.setLinkId("linkid");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            cmppDeliverPacket.setMsgFmt((byte)15);
            
        }else{
            //自动返回上行
            cmppDeliverPacket.setDestId(cmppSubmitPacket.getSrcId());
            cmppDeliverPacket.setDestTerminalId(cmppSubmitPacket.getDestTerminateIds());
            cmppDeliverPacket.setRegisteredDelivery(false);
            cmppDeliverPacket.setSrcTerminalId(cmppSubmitPacket.getDestTerminateIds());
            cmppDeliverPacket.setSrcTerminalType((byte)0);
            cmppDeliverPacket.setServiceId(cmppSubmitPacket.getServiceId());
            cmppDeliverPacket.setMsgContent(cmppSubmitPacket.getMsgContent());
            cmppDeliverPacket.setMsgId(MessageIdGenerator.getMessageIdGenerator().getMsgId((short)0));
            try {
                cmppDeliverPacket.setLinkId("linkid");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            cmppDeliverPacket.setMsgFmt((byte)15);
            
        }
        
        
        
        UserRunTime userRunTime = sysRunTimeService.getUserRunTime(user);
        if(userRunTime != null){
            cmppDeliverPacket.autoDeliverSubmitTime = System.currentTimeMillis();
            if(userRunTime.addMo(cmppDeliverPacket,false)){
            }else{
                InvokeRateUtil.invokeRate_auto_deliver_fail.count();
                //自动回复下行量大导致状态报告返回相对缓慢,引发内存积压,必要是抛弃自动返回的状态报告。
            }
        }
        
    }
	


	private List<SubmitReqResp> getSubmitReqResps(CmppSubmitPacket cmppSubmitPacket,CmppSubmitRespPacket cmppSubmitRespPacket,Version version){
	    String[] terminals = cmppSubmitPacket.getDestTerminalId();
        long msgId = cmppSubmitRespPacket.getMsgId();
        int index = 0;
        
        List<SubmitReqResp> submitReqResps = new ArrayList<SubmitReqResp>();
        
        for(String terminal:terminals){
            CmppSubmitPacket cmppSubmitPacketSingle = new CmppSubmitPacket(version);
            BeanUtils.copyProperties(cmppSubmitPacket, cmppSubmitPacketSingle);
            cmppSubmitPacketSingle.setDestTerminalId(new String[]{terminal});
            
            CmppSubmitRespPacket cmppSubmitRespPacketSingle = new CmppSubmitRespPacket(version);
            cmppSubmitRespPacketSingle.setMsgId(msgId + index);
            index ++;
            
            submitReqResps.add(new SubmitReqResp(cmppSubmitPacketSingle,cmppSubmitRespPacketSingle));
        }
        return submitReqResps;
	}
	
}


class SubmitReqResp{
    SubmitReqResp(CmppSubmitPacket cmppSubmitPacket,CmppSubmitRespPacket cmppSubmitRespPacket){
        this.cmppSubmitPacket = cmppSubmitPacket;
        this.cmppSubmitRespPacket = cmppSubmitRespPacket;
    }
    CmppSubmitPacket cmppSubmitPacket;
    CmppSubmitRespPacket cmppSubmitRespPacket;
}